﻿using Layui.Entities;
using System;
using System.Collections.Generic;
using System.Text;
using Layui.Core;
using Microsoft.EntityFrameworkCore;
using System.Linq;
using Layui.Core.Infrastructure;

namespace Layui.Services.SysLog
{
    public class SysLogService : ISysLogService
    {
        private LayuiDbContext _LayuiDbContext;
        private IWebHelper _webHelper;

        public SysLogService(LayuiDbContext LayuiDbContext,
            IWebHelper webHelper)
        {
            this._webHelper = webHelper;
            this._LayuiDbContext = LayuiDbContext;
        }

        /// <summary>
        /// 清理所有日志
        /// </summary>
        public void ClearLog()
        {
            _LayuiDbContext.Database.ExecuteSqlCommand("truncate table SysLog");
        }

        public void Debug(string message, Exception exception = null)
        {
            FilteredLog(EnumLevel.Debug, message, exception);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="message"></param>
        /// <param name="exception"></param>
        public void Error(string message, Exception exception = null)
        {
            FilteredLog(EnumLevel.Error, message, exception);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="message"></param>
        /// <param name="exception"></param>
        public void Fatal(string message, Exception exception = null)
        {
            FilteredLog(EnumLevel.Fatal, message, exception);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="message"></param>
        /// <param name="exception"></param>
        public void Information(string message, Exception exception = null)
        {
            FilteredLog(EnumLevel.Information, message, exception);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="level"></param>
        /// <param name="shortMessage"></param>
        /// <param name="fullMessage"></param>
        /// <returns></returns>
        public Entities.SysLog InsertLog(EnumLevel level, string shortMessage, string fullMessage = null)
        {
            var log = new Entities.SysLog()
            {
                Id = Guid.NewGuid(),
                FullMessage = fullMessage,
                ShortMessage = shortMessage,
                Level = (int)level,
                CreationTime = DateTime.Now,
                IpAddress = _webHelper.GetIPAddress(),
                PageUrl = _webHelper.GetUrl(),
                ReferrerUrl = _webHelper.GetUrlReferrer()
            };
            _LayuiDbContext.SysLogs.Add(log);
            _LayuiDbContext.SaveChanges();
            return log;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="arg"></param>
        /// <param name="page"></param>
        /// <param name="size"></param>
        /// <returns></returns>
        public IPagedList<Entities.SysLog> Search(LogSearchArg arg, int page, int size)
        {
            var query = _LayuiDbContext.SysLogs.AsQueryable();
            if (arg != null)
            {
                if (arg.level != null)
                    query = query.Where(o => o.Level == arg.level);
            }
            query = query.OrderByDescending(o => o.CreationTime);
            return new PagedList<Entities.SysLog>(query, page, size);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="message"></param>
        /// <param name="exception"></param>
        public void Warning(string message, Exception exception = null)
        {
            FilteredLog(EnumLevel.Warning, message, exception);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="logger"></param>
        /// <param name="level"></param>
        /// <param name="message"></param>
        /// <param name="exception"></param>
        private void FilteredLog(EnumLevel level, string message, Exception exception = null)
        {
            try
            {
                string fullMessage = exception == null ? string.Empty : exception.ToString();
                InsertLog(level, message, fullMessage);
            }
            catch (Exception)
            {
                //log4net
            }
        }
    }
}
